package com.cn.xiaonuo.tcrfinance.tcrusers.service.impl;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.cn.xiaonuo.common.constant.Status;
import com.cn.xiaonuo.common.entity.BusinessMessage;
import com.cn.xiaonuo.common.tools.RestTemplateUtil;
import com.cn.xiaonuo.common.utils.DateUtils;
import com.cn.xiaonuo.common.utils.OrderNumGeneration;
import com.cn.xiaonuo.common.utils.StringUtils;
import com.cn.xiaonuo.core.util.PoiUtil;
import com.cn.xiaonuo.core.util.RedisKeyUtil;
import com.cn.xiaonuo.tcrfinance.sysmgmt.entity.SysUserHpcEntity;
import com.cn.xiaonuo.tcrfinance.tcrorder.entity.PvOrder;
import com.cn.xiaonuo.tcrfinance.tcrorder.entity.PvPossessionGoods;
import com.cn.xiaonuo.tcrfinance.tcrorder.entity.PvPossessionGoodsLog;
import com.cn.xiaonuo.tcrfinance.tcrorder.entity.PvReleaseBase;
import com.cn.xiaonuo.tcrfinance.tcrorder.mapper.PvOrderMapper;
import com.cn.xiaonuo.tcrfinance.tcrorder.mapper.PvPossessionGoodsLogMapper;
import com.cn.xiaonuo.tcrfinance.tcrorder.mapper.PvPossessionGoodsMapper;
import com.cn.xiaonuo.tcrfinance.tcrorder.mapper.PvReleaseBaseMapper;
import com.cn.xiaonuo.tcrfinance.tcrusers.entity.PvLoginUser;
import com.cn.xiaonuo.tcrfinance.tcrusers.entity.PvWallet;
import com.cn.xiaonuo.tcrfinance.tcrusers.entity.PvWalletShop;
import com.cn.xiaonuo.tcrfinance.tcrusers.entity.PvWalletShopLog;
import com.cn.xiaonuo.tcrfinance.tcrusers.mapper.PvLoginUserMapper;
import com.cn.xiaonuo.tcrfinance.tcrusers.mapper.PvWalletLogMapper;
import com.cn.xiaonuo.tcrfinance.tcrusers.mapper.PvWalletMapper;
import com.cn.xiaonuo.tcrfinance.tcrusers.mapper.PvWalletShopMapper;
import com.cn.xiaonuo.tcrfinance.tcrusers.service.IdentityRevocationService;
import com.cn.xiaonuo.tcrfinance.tcrusers.service.LoginService;
import com.cn.xiaonuo.tcrfinance.tcrusers.service.PvLoginUserService;
import com.cn.xiaonuo.tcrfinance.tcrusers.vo.ExUserTransferenceVo;
import com.cn.xiaonuo.tcrfinance.tcrusers.vo.GwqClearVo;
import com.cn.xiaonuo.tcrfinance.tcrusers.vo.IdentityRevocationVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.hutool.core.date.DateTime.now;

/**
 * @author likui
 * @date 2023/10/17 16:22
 **/
@Slf4j
@Service
public class IdentityRevocationServiceImpl implements IdentityRevocationService {
    @Autowired
    private LoginService loginService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private PvLoginUserMapper pvLoginUserMapper;
    @Autowired
    private PvWalletShopMapper pvWalletShopMapper;
    @Autowired
    private PvLoginUserService pvLoginUserService;
    @Resource
    private Environment environment;
    @Autowired
    private RestTemplateUtil restTemplateUtil;
    @Autowired
    private PvOrderMapper pvOrderMapper;
    @Autowired
    private PvReleaseBaseMapper pvReleaseBaseMapper;
    @Autowired
    private PvWalletLogMapper pvWalletLogMapper;
    @Autowired
    private PvLoginUserServiceImpl pvLoginUserServiceImpl;
    @Autowired
    private PvWalletMapper pvWalletMapper;
    @Autowired
    private PvPossessionGoodsMapper pvPossessionGoodsMapper;
    @Autowired
    private PvPossessionGoodsLogMapper pvPossessionGoodsLogMapper;

    @Override
    public BusinessMessage identityRevocation(MultipartFile file) {
        BusinessMessage message = new BusinessMessage();
        SysUserHpcEntity currentLoginUser = loginService.getCurrentLoginUser();
        if (ObjectUtils.isEmpty(currentLoginUser)){
            message.setCode("-1");
            message.setMessage("无登录用户!");
            message.setSuccess(false);
            return message;
        }
        try {
            log.info("用户{}操作批量撤销体验用户身份，时间：[{}]",currentLoginUser.getUserId(),new Date());
            List<IdentityRevocationVo> identityRevocationVos = PoiUtil.importExcel(file, 0, 1, IdentityRevocationVo.class);
            if (identityRevocationVos.size()>500){
                message.setSuccess(false);
                message.setCode("-1");
                message.setMessage("数据量超出限制范围!");
                return message;
            }
            List<IdentityRevocationVo> list = new ArrayList<>();
            List<Integer> userIdList = identityRevocationVos.stream().map(IdentityRevocationVo::getUserId).filter(Objects::nonNull).collect(Collectors.toList());
            if (userIdList.size()<1){
                message.setSuccess(false);
                message.setCode("-1");
                message.setMessage("用户id不能为空!");
                return message;
            }
            //用户校验，查询是否有部分和条件的
            QueryWrapper<PvLoginUser> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("id,accounts,phone,real_name as realName");
            queryWrapper.in("id",userIdList).and(i->i.notIn("user_type",1).or().notIn("status",3));
            List<PvLoginUser> pvLoginUsers = pvLoginUserMapper.selectList(queryWrapper);
            if (pvLoginUsers.size()>0){
                list = pvLoginUsers.stream().map(user -> {
                    IdentityRevocationVo vo = new IdentityRevocationVo();
                    vo.setUserId(user.getId());
                    vo.setAccounts(user.getAccounts());
                    vo.setPhone(user.getPhone());
                    vo.setUserName(user.getRealName());
                    vo.setRemarks("体验身份不满足!");
                    return vo;
                }).collect(Collectors.toList());
            }
            if (list.size()>0){
                message.setData(list);
                message.setSuccess(false);
                message.setCode("-1");
                message.setMessage("数据异常，请核对后重试!");
                return message;
            }
            // 用户对应的excel金额
            Map<Integer, BigDecimal> userAmountMap = identityRevocationVos.stream().collect(Collectors.toMap(IdentityRevocationVo::getUserId, IdentityRevocationVo::getPersonalAmount));
            // 用户对应的钱包金额
            List<IdentityRevocationVo> totalBalanceList = pvWalletShopMapper.selectTotalBalanceList(userIdList);
            // 筛选出钱包余额<excel余额
            List<IdentityRevocationVo> errorUser = totalBalanceList.stream().filter(item -> Judge(item, userAmountMap)).collect(Collectors.toList());
            if (errorUser.size()>0){
                message.setData(errorUser);
                message.setSuccess(false);
                message.setCode("-1");
                message.setMessage("数据异常，请核对后重试!");
                return message;
            }

            for (IdentityRevocationVo revocationVo:identityRevocationVos){
                BusinessMessage deductible = pvLoginUserService.deductible(revocationVo);
                if (!deductible.getCode().equals("200")){
                    log.info("用户[{}],回收体验金操作失败，原因{}",revocationVo.getUserId(),deductible.getMessage());
                    Object data = deductible.getData();
                    if (ObjectUtils.isNotEmpty(data)){
                        IdentityRevocationVo user= JSONObject.parseObject(JSONObject.toJSONString(data),IdentityRevocationVo.class);
                        list.add(user);
                    }
                }
            }
            if (list.size()>0){
                message.setData(list);
            }
            message.setCode("200");
            message.setMessage("操作成功");
            message.setSuccess(true);
        }catch (Exception e){
            log.info("用户[{}]回收体验金操作异常，原因：{}",currentLoginUser.getUserId(),e.getMessage());
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("数据异常，请核对后重试!");
            e.printStackTrace();
        }
        return message;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BusinessMessage jybExperienceGwqClear(MultipartFile file) {
        BusinessMessage message = new BusinessMessage();
        SysUserHpcEntity currentLoginUser = loginService.getCurrentLoginUser();
        if (ObjectUtils.isEmpty(currentLoginUser)){
            message.setCode("-1");
            message.setMessage("无登录用户!");
            message.setSuccess(false);
            return message;
        }
        log.info("体验用户数据清空任务执行开始，执行人[{}]，执行时间{}",currentLoginUser.getUserId(),new Date());
        List<IdentityRevocationVo> identityRevocationVos = PoiUtil.importExcel(file, 0, 1, IdentityRevocationVo.class).stream().filter(i-> StringUtils.isNotBlank(i.getPhone())).collect(Collectors.toList());
        if (identityRevocationVos.size()>500){
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("数据量超出限制范围!");
            return message;
        }
        List<String> phones = identityRevocationVos.stream().map(IdentityRevocationVo::getPhone).filter(Objects::nonNull).collect(Collectors.toList());
        if (phones.size()<1){
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("电话号码不能为空!");
            return message;

        }
        List<IdentityRevocationVo> list = new ArrayList<>();
        //用户校验，查询是否有部分和条件的
        QueryWrapper<PvLoginUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id,accounts,phone,real_name as realName,user_type");
        queryWrapper.in("phone",phones);
        List<PvLoginUser> pvLoginUsers = pvLoginUserMapper.selectList(queryWrapper);
        List<PvLoginUser> loginUsers = pvLoginUsers.stream().filter(i -> i.getUserType() == 0).collect(Collectors.toList());
        if (loginUsers.size()>0){
            list = loginUsers.stream().map(user -> {
                IdentityRevocationVo vo = new IdentityRevocationVo();
                vo.setUserId(user.getId());
                vo.setAccounts(user.getAccounts());
                vo.setPhone(user.getPhone());
                vo.setUserName(user.getRealName());
                vo.setRemarks("体验身份不满足,或数据已处理!");
                return vo;
            }).collect(Collectors.toList());
        }
        if (list.size()>0){
            message.setData(list);
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("该表单有非体验用户，请核对后重试!");
            return message;
        }
        //查询用户是否有现金订单
        List<Integer> userIdList = pvLoginUsers.stream().map(PvLoginUser::getId).collect(Collectors.toList());
        LambdaQueryWrapper<PvOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(PvOrder::getId,PvOrder::getDelistingUserId,PvOrder::getSerialNumber);
        wrapper.in(PvOrder::getDelistingUserId,userIdList);
        wrapper.eq(PvOrder::getPaymentState,1);
        wrapper.eq(PvOrder::getStatus,1);
        wrapper.in(PvOrder::getPaymentChannel,1,2,3,13,21,24);
        wrapper.in(PvOrder::getPurchaseMethod,1,3);
        wrapper.groupBy(PvOrder::getDelistingUserId);
        List<PvOrder> pvOrders = pvOrderMapper.selectList(wrapper);
        Map<Integer, PvLoginUser> collect = pvLoginUsers.stream().collect(Collectors.toMap(PvLoginUser::getId, t -> t));
        if (pvOrders.size()>0){
            for (PvOrder order:pvOrders){
                IdentityRevocationVo revocationVo = this.errorObject(order.getDelistingUserId(), collect,"该用户有现金交易订单!");
                list.add(revocationVo);
            }
        }
        if (list.size()>0){
            message.setData(list);
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("该表单有现金交易订单，请核对后重试!");
            return message;
        }
        //查询当然是否有卖出
        String format = DateUtils.ymd.format(new Date());
        LambdaQueryWrapper<PvReleaseBase> baseWrapper = new LambdaQueryWrapper<>();
        baseWrapper.in(PvReleaseBase::getUserId,userIdList);
        baseWrapper.eq(PvReleaseBase::getTypes,2);
        baseWrapper.groupBy(PvReleaseBase::getUserId);
        baseWrapper.likeRight(PvReleaseBase::getCTime,format);
        List<PvReleaseBase> pvReleaseBases = pvReleaseBaseMapper.selectList(baseWrapper);
        if (pvReleaseBases.size()>0){
            for (PvReleaseBase base:pvReleaseBases){
                IdentityRevocationVo revocationVo = this.errorObject(base.getUserId(), collect,"该用户今日有卖出订单!");
                list.add(revocationVo);
            }
        }
        if (list.size()>0){
            message.setData(list);
            message.setSuccess(false);
            message.setCode("-1");
            message.setMessage("该表单今日有卖出订单，请核对后重试!");
            return message;
        }
        try {
            pvReleaseBaseMapper.update(null, new UpdateWrapper<PvReleaseBase>().set("purchase_num", 0).set("types", 8).in("user_id", userIdList).in("types", 1, 5));
            pvOrderMapper.update(null, new UpdateWrapper<PvOrder>()
                    .set("payment_state", 2).set("status", 0).set("remark", "数据消除，清除该用户平台订单")
                    .and(i -> i.in("delisting_user_id", userIdList).or().in("listing_user_id", userIdList))
                    .and(c->c.and(a->a.eq("payment_state", 1).notIn("purchase_method",4)).or(s->s.eq("payment_state",2).eq("purchase_method",4))));
            String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            LambdaQueryWrapper<PvWallet> walletWrapper = new LambdaQueryWrapper<>();
            walletWrapper.gt(PvWallet::getAvailableBalance, 0);
            walletWrapper.in(PvWallet::getUserId, userIdList);
            List<PvWallet> pvWallets = pvWalletMapper.selectList(walletWrapper);
            for (PvWallet wallet : pvWallets) {
                pvLoginUserServiceImpl.moneyOperation(wallet.getUserId(), 2, wallet.getAvailableBalance());
                pvWalletLogMapper.insertWalletLogByUserId(wallet.getUserId(), null, wallet.getAvailableBalance(), "数据消除，清除该用户平台余额", currentTime, 18, currentLoginUser.getUserId().intValue());
            }
            //处理商户钱包
           this.walletShopHandle(userIdList,currentLoginUser.getUserId());
            //处理体验用户商品
            this.goodsHandle(userIdList);
            pvLoginUserMapper.update(null,new UpdateWrapper<PvLoginUser>().set("user_type",0).in("id",userIdList));
            //清空购物券
           this.gwqClear(phones);
           message.setCode("200");
           message.setMessage("操作成功");
           message.setSuccess(true);
        } catch (Exception e) {
            identityRevocationVos.forEach(i->i.setRemarks("系统出现异常，请两分钟后重试!"));
            log.error("体验用户数据清除失败，原因：{}",e.getMessage());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            message.setSuccess(false);
            message.setMessage("体验用户数据清除失败!");
            message.setCode(Status.failCode);
            message.setData(identityRevocationVos);
        }
        return message;
    }

    //处理体验用户商品
    public void goodsHandle(List<Integer> userIdList) {
        LambdaQueryWrapper<PvPossessionGoods> goodsWrapper = new LambdaQueryWrapper<>();
        goodsWrapper.in(PvPossessionGoods::getUserId,userIdList).and(i->i.gt(PvPossessionGoods::getPossessNumber,0).or().gt(PvPossessionGoods::getCansellNumber,0));
        List<PvPossessionGoods> pvPossessionGoods = pvPossessionGoodsMapper.selectList(goodsWrapper);
        for (PvPossessionGoods pvPossessionGood:pvPossessionGoods){
            pvPossessionGoodsMapper.update(null,new UpdateWrapper<PvPossessionGoods>().set("possess_number",0).set("cansell_number",0).eq("id",pvPossessionGood.getId()));
            PvPossessionGoodsLog pvPossessionGoodsLog = new PvPossessionGoodsLog();
            pvPossessionGoodsLog.setUserId(pvPossessionGood.getUserId());
            pvPossessionGoodsLog.setGoodsId(pvPossessionGood.getId());
            pvPossessionGoodsLog.setProductId(pvPossessionGood.getProductId());
            pvPossessionGoodsLog.setProductName(pvPossessionGood.getProductName());
            pvPossessionGoodsLog.setBeforFrozenNumber(pvPossessionGood.getPossessNumber());
            pvPossessionGoodsLog.setAfterFrozenNumber(BigDecimal.ZERO);
            pvPossessionGoodsLog.setBeforeNumber(pvPossessionGood.getCansellNumber());
            pvPossessionGoodsLog.setAfterNumber(BigDecimal.ZERO);
            pvPossessionGoodsLog.setChangeNumber(pvPossessionGood.getCansellNumber().add(pvPossessionGood.getPossessNumber()));
            pvPossessionGoodsLog.setRemark("数据消除，清除该用户商品拥有数");
            pvPossessionGoodsLogMapper.insert(pvPossessionGoodsLog);
        }
    }
    //处理体验用户商户钱包
    public void walletShopHandle(List<Integer> userIdList,Long operationId){
        LambdaQueryWrapper<PvWalletShop> walletShopWrapper = new LambdaQueryWrapper<>();
        walletShopWrapper.in(PvWalletShop::getUserId, userIdList);
        walletShopWrapper.gt(PvWalletShop::getAvailableBalance, 0);
        List<PvWalletShop> pvWalletShops = pvWalletShopMapper.selectList(walletShopWrapper);
        for (PvWalletShop walletShop : pvWalletShops) {
            pvWalletShopMapper.updateWalletShopInfoByShopIdAndUserId(walletShop.getShopId(), walletShop.getUserId(), walletShop.getAvailableBalance(), 2);
            PvWalletShopLog pvWalletShopLog = new PvWalletShopLog();
            pvWalletShopLog.setUserId(walletShop.getUserId());
            pvWalletShopLog.setOrderId(null);
            pvWalletShopLog.setRemarks("数据消除，清除该用户商户余额");
            pvWalletShopLog.setCreateTime(now());
            pvWalletShopLog.setTypes(18);
            pvWalletShopLog.setOperation(operationId.intValue());
            pvWalletShopLog.setShopId(walletShop.getShopId());
            pvWalletShopLog.setShopName(walletShop.getShopName());
            pvWalletShopLog.setChangeBalance(walletShop.getAvailableBalance());
            pvWalletShopLog.setUpdateTime(now());

            pvWalletShopMapper.addPvWalletShopLog(pvWalletShopLog);
        }
    }

    public void gwqClear(List<String> phones){

        try {
            GwqClearVo clearVo=new GwqClearVo();
            clearVo.setPhones(phones);
            String url = environment.getProperty("gwq.gwqUrl");
            String method = environment.getProperty("gwq.jybExperienceGwqClear");
            String token = environment.getProperty("gwq.token");
            String json = JSON.toJSONString(clearVo);
            log.info("椒易宝体验用户购物券消费扣除远程调用入参信息： {}", json);
            Map data = restTemplateUtil.post(url, method, json, token);
            log.info("椒易宝体验用户购物券消费扣除远程调用返回结果： {}", data);
        } catch (Exception e) {
            log.error("椒易宝体验用户购物券消费扣除远程调用失败!原因：[{}]", e.getMessage());
            throw new RuntimeException("椒易宝体验用户购物券消费扣除远程调用失败,原因:"+e.getMessage());
        }
    }
    /**
     * 钱包余额少于excel金额
     * @param item
     * @param userAmountMap
     * @return
     */
    private boolean Judge(IdentityRevocationVo item, Map<Integer, BigDecimal> userAmountMap) {
        return item.getPersonalAmount().compareTo(userAmountMap.get(item.getUserId())) < 0;
    }

    public IdentityRevocationVo errorObject(Integer userId,Map<Integer, PvLoginUser> collect,String remarks){
        PvLoginUser user = collect.get(userId);
        IdentityRevocationVo vo = new IdentityRevocationVo();
        vo.setUserId(userId);
        vo.setAccounts(user.getAccounts());
        vo.setPhone(user.getPhone());
        vo.setUserName(user.getRealName());
        vo.setRemarks(remarks);
        return vo;
    }
}
